import { isNaN } from 'lodash-es'

export type FormValidator = (
  value: any,
  callback: (error?: string) => void
) => void

// 正则通用验证器
export function regExpValidateHandler(
  value: string | number,
  reg: RegExp,
  errMsg: string,
) {
  if (!reg.test(value.toString())) {
    return errMsg
  }
  return undefined
}

export function validateHandler<T = string | number | string[] | number[]>(
  value: T,
  handler: (data: string) => string | undefined,
): string | undefined {
  if (!Array.isArray(value)) {
    return handler(((value || '') as string | number).toString())
  }
  let errMsg: string | undefined
  value.find((item, i) => {
    errMsg = handler(item, i)
    if (errMsg) {
      return true
    }
    return false
  })
  return errMsg
}

// 验证正则
export const regexpMap = {
  // ipv4地址
  ipv4: /^((1?[1-9]?\d|[12][0-4]\d|25[0-5])\.){3}(1?[1-9]?\d|[12][0-4]\d|25[0-5])$/,
  // ipv6地址
  ipv6: /^(?:(?:[0-9A-F]{1,4}:){7}[0-9A-F]{1,4}|(?:[0-9A-F]{1,4}:){1,7}:|:(?::[0-9A-F]{1,4}){1,7}|(?:(?:[0-9A-F]{1,4}:){1,6}|[0-9A-F]{1,4}::(?:[0-9A-F]{1,4}:){0,5}):[0-9A-F]{1,4}|fe80:(?::[0-9A-F]{0,4}){0,4}%[0-9A-Z]+|::ffff(:0{1,4})?:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)|(?:[0-9A-F]{1,4}:){1,4}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d))$/i,
  // ipv4AndPort:
  //   /^((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])(?::(?:[0-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]))?$/,
  // ipv6AndPort:
  //   /(([0-9a-fA-F]{1,4}:){7}([0-9a-fA-F]{1,4}|:)|(([0-9a-fA-F]{1,4}:){1,7}|:):([0-9a-fA-F]{1,4}:){1,6}([0-9a-fA-F]{1,4}|:)|(([0-9a-fA-F]{1,4}:){1,6}|:):([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|(([0-9a-fA-F]{1,4}:){1,5}|:):([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|(([0-9a-fA-F]{1,4}:){1,4}|:):([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|(([0-9a-fA-F]{1,4}:){1,3}|:):([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|(([0-9a-fA-F]{1,4}:){1,2}|:):[0-9a-fA-F]{1,4}:(([0-9a-fA-F]{1,4}:){1,6})|([0-9a-fA-F]{1,4}|:):(([0-9a-fA-F]{1,4}:){1,7}|:))(:\d{1,5})?$/,
  // // 域名
  domain:
    // /^(?=^.{3,255}$)([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-z]{2,11}$/,
    // /^(?=^.{3,255}$)([a-zA-Z0-9]+(-[a-zA-Z0-9]+)?\.)+[a-z]{2,11}$/,
    /^(?=.{3,255}$)([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,11}$/i, // 可以校验带-的域名
  /// ^(?=^.{3,255}$)((?!.*--)[a-zA-Z0-9]([a-zA-Z0-9-]{0,55}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,11}(?<!-)$/
  // // 域名（可校验端口号）
  domainAndPort:
    /^(?=.{3,255})([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-z]{2,11}(:([1-9]\d{0,3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5]))?$/,
  // //ipv4和域名
  // ipv4OrDomain:
  //   /^(?:(?:(?:1?[1-9]?\d|[1-2][0-4]\d|25[0-5])\.){3}(?:1?[1-9]?\d|[1-2][0-4]\d|25[0-5]))|(?=^.{3,255}$)([a-zA-Z0-9]+(-[a-zA-Z0-9]+)*\.)+[a-zA-Z]{2,11}$/,
  // url地址
  url: /^http(s)?:\/\/(?:[a-zA-Z\d]+(?:-[a-zA-Z\d]+)*\.)+[a-z]{2,11}|localhost|(?:(?:1?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:1?\d{1,2}|2[0-4]\d|25[0-5])(?::\d{1,5})?(?:\/[\w\-~%!$&'()*+,;=:@/]*)?$/,
  // //url具体到文件名
  // urlWithFileName:
  //   /^http(s)?:\/\/(((([a-zA-Z\d]+-?)+(?<!-)\.)+[a-z]{2,11})|((1?[1-9]?\d|[1-2][0-4]\d|25[0-5])\.){3}(1?[1-9]?\d|[1-2][0-4]\d|25[0-5]))(:([1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]))?(\/\S*)?$/,
  // //url具体到文件类型 (\/\S*\.[a-zA-Z]{2,})?$/ ?代表是否需要必填文件类型
  // urlWithFileType:
  //   /^http(s)?:\/\/(((([a-zA-Z\d]+-?)+(?<!-)\.)+[a-z]{2,11})|((1?[1-9]?\d|[1-2][0-4]\d|25[0-5])\.){3}(1?[1-9]?\d|[1-2][0-4]\d|25[0-5]))(:([1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]))?((\/\S*\.[a-zA-Z]{2,}|\/.\/*))?$/,
  // // http https 可选 url具体到文件类型 (\/\S*\.[a-zA-Z]{2,})?$/ ?代表是否需要必填文件类型
  // optionalProtocolUrlWithFileType:
  //   /^(?:http(s)?:\/\/)?([a-zA-Z\d-]+\.)+[a-zA-Z]{2,11}(\/[^\s]*)?(\.[a-zA-Z]{2,4})?$/,
  // // http https 必填 url具体到文件类型 (\/\S*\.[a-zA-Z]{2,})?$/ ?代表是否需要必填文件类型
  // protocolUrlWithFileType:
  //   /^(?:http(s)?:\/\/)([a-zA-Z\d-]+\.)+[a-zA-Z]{2,11}(\/[^\s]*)?(\.[a-zA-Z]{2,4})?$/,
  // // 无协议url地址 端口号可选 有路径
  // noProtocolUrl:
  //   /^([\w-]+\.)+[\w-]+(:([1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]))?(\/\S*)?$/,
  // // 无协议url地址 无路径 端口号可选
  // noProtocolNoEndWithStrUrl:
  //   /^([\w-]+\.)*[\w-]+(:([1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]))?$/,
  // // 无端口号url地址
  // noPortUrl: /^http(s)?:\/\/([\w-]+\.)+[\w-]+(\/\S*)?$/,
  // // 无协议无端口号url地址
  // noProtocolAndPortUrl: /^([\w-]+\.)+[\w-]+(\/\S*)?$/,
  // //校验金额
  // balance: /^(?!0\d)\d{1,5}(?:\.\d{1,2})?$/,
  // // 邮箱

  // qq: /^[1-9][0-9]{4,11}$/,
  // phone:
  //   /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/,
  // // Telegram
  // telegram: /^https:\/\/t\.me\/[a-zA-Z0-9]{1,88}$/,
  // // Skype
  // skype: /^https:\/\/join\.skype\.com\/invite\/[A-Za-z0-9]{1,100}$/,
  // cname: /^(?!-)(?!.*--)[a-zA-Z0-9-]{6,20}(?<!-)$/,
  email:
    /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\])|(([a-z\-0-9]+\.)+[a-z]{2,}))$/i,
}

// 验证端口号
export const validateSitePort: FormValidator = (
  value: number | string | string[] | number[],
  callback: (error?: string) => void,
) => {
  callback(
    validateHandler(value, (data) => {
      const port = Number(data)
      if (isNaN(port)) {
        return '端口号格式错误'
      }
      if (port < 1 || port > 65535) {
        return '端口范围：1~65535'
      }
    }),
  )
}

// 验证IPv4地址
export const validateIpv4: FormValidator = (
  value: number | string | string[] | number[],
  callback: (error?: string) => void,
) => {
  console.log(value)
  callback(
    validateHandler(value, data =>
      regExpValidateHandler(data, regexpMap.ipv4, 'IP地址格式错误')),
  )
}

// 验证IPv6地址
export const validateIpv6: FormValidator = (
  value: number | string | string[] | number[],
  callback: (error?: string) => void,
) => {
  callback(
    validateHandler(value, data =>
      regExpValidateHandler(data, regexpMap.ipv4, 'IP地址格式错误')),
  )
}

// 验证域名
export const validateDomain: FormValidator = (
  value: number | string | string[] | number[],
  callback: (error?: string) => void,
) => {
  callback(
    validateHandler(value, data =>
      regExpValidateHandler(data, regexpMap.domain, '域名格式错误')),
  )
}

// 验证域名，可携带端口号
export const validateDomainAndPort: FormValidator = (
  value: number | string | string[] | number[],
  callback: (error?: string) => void,
) => {
  callback(
    validateHandler(value, data =>
      regExpValidateHandler(
        data,
        regexpMap.domainAndPort,
        data.includes(':') ? '域名格式错误，端口范围为1~65535' : '域名格式错误',
      )),
  )
}

// 验证泛域名，包括正常域名
// export const validatePanDomain: FormValidator = (value: any, callback) => {
//   callback(
//     validateHandler(value, (data) => {
//       const error = '域名格式错误'
//       if (data.startsWith('*.')) {
//         data = data.substring(2, data.length - 1)
//       }
//       return regExpValidateHandler(data, regexpMap.domain, error)
//     }),
//   )
// }

// 验证管理端地址
// export const validateMgrAddr: FormValidator = (
//   value: string,
//   callback: (error?: string) => void,
// ) => {
//   const ipv4 = regexpMap.ipv4
//   const ipv6 = regexpMap.ipv6
//   const ipv4AndPort = regexpMap.ipv4AndPort
//   const ipv6AndPort = regexpMap.ipv6AndPort
//   const domain = regexpMap.domain
//   const domainAndPort = regexpMap.domainAndPort
//   if (!value) {
//     return callback('请输入管理端地址')
//   }
//   if (!value.startsWith('http://') && !value.startsWith('https://')) {
//     return callback('管理端地址错误')
//   }
//   const index = value.indexOf('://')
//   const host = value.substring(index + 3).toString()

//   if (
//     ipv4.test(host)
//     || ipv6.test(host)
//     || ipv4AndPort.test(host)
//     || ipv6AndPort.test(host)
//     || domain.test(host)
//     || domainAndPort.test(host)
//   ) {
//     return callback()
//   } else {
//     return callback('管理端地址错误')
//   }
// }

// 验证文件后缀
// export const validateSuffix: FormValidator = (
//   value: number | string | string[] | number[],
//   callback: (error?: string) => void,
// ) => {
//   // const reg = /^[A-Za-z0-9*-,/]+$/
//   const reg = /^([A-Z0-9*-/]+(,[A-Z0-9*-/]+)*)?$/i
//   callback(
//     validateHandler(value, (data) => {
//       if (data.includes('.'))
//         return callback('格式错误,请检查后缀是否正确')
//       if (data.startsWith(',') || data.endsWith(','))
//         return callback('请输入文件后缀，多个值用英文逗号隔开，区分大小写')
//       return regExpValidateHandler(
//         data,
//         reg,
//         '请输入文件后缀，多个值用英文逗号隔开，区分大小写',
//       )
//     }),
//   )
// }

// 验证账号
export const validateAccount: FormValidator = (
  value: number | string | string[] | number[],
  callback: (error?: string) => void,
) => {
  const reg = /^[\w@]{4,18}$/
  callback(
    validateHandler(value, data =>
      regExpValidateHandler(
        data,
        reg,
        '请输入4-18个字符，可包含英文字母、数字、下划线',
      )),
  )
}

/** 密码验证 */
export function validatePassword(
  value: string,
  callback: (error?: string) => void,
) {
  // 完整正则
  //  const reg =
  //   /^(?=[\w()`!@#$%^&*\-+=|{}[\]:;'<>,.?]*\d)(?=[\w()`!@#$%^&*\-+=|{}[\]:;'<>,.?]*[()`!@#$%^&*_\-+=|{}[\]:;'<>,.?])(?=[\w()`!@#$%^&*\-+=|{}[\]:;'<>,.?]*[a-z])(?=[\w()`!@#$%^&*\-+=|{}[\]:;'<>,.?]*[A-Z])([\w()`!@#$%^&*\-+=|{}[\]:;'<>,.?]){8,20}$/
  const reg1 = /[_()`~!@#$%^&*\-+=|{}[\]:;'<>,.?]/ // 包含特殊字符（除空格）
  const reg2 = /\d/ // 包含数字
  const reg3 = /[a-z]/ // 包含小写
  const reg4 = /[A-Z]/ // 包含大写
  const error
    = '请输入8-20个字符，需包含大小写英文字母、数字和标点符号（除空格）'
  if (!value) {
    return callback('请输入密码')
  }
  if (!value.match(reg1)) {
    return callback(error)
  }
  if (!value.match(reg2)) {
    return callback(error)
  }
  if (!value.match(reg3)) {
    return callback(error)
  }
  if (!value.match(reg4)) {
    return callback(error)
  }
  if (value.length < 8 || value.length > 20) {
    return callback(error)
  }
  return callback()
}

// 验证 验证码
export const validateVerifyCode: FormValidator = (
  value: number | string | string[] | number[],
  callback: (error?: string) => void,
) => {
  const reg = /^\d{6}$/
  callback(
    validateHandler(value, data =>
      regExpValidateHandler(data, reg, '请输入6位数字验证码')),
  )
}

// 验证URL地址
export const validateURL: FormValidator = (
  value: number | string | string[] | number[],
  callback: (error?: string) => void,
) => {
  callback(
    validateHandler(value, (data) => {
      if (data.length > 2048) {
        return '长度不可超过2048位字符'
      }
      const errMsg = regExpValidateHandler(
        data,
        regexpMap.url,
        '请输入格式正确并带有协议的URL',
      )
      if (errMsg) {
        return errMsg
      }
      const u = new URL(data)
      if (u.hostname.length > 63) {
        return '域名长度不可超过63位'
      }
    }),
  )
}

// 验证URL路径
export const validateUrlPath: FormValidator = (
  value: number | string | string[] | number[],
  callback: (error?: string) => void,
) => {
  callback(
    validateHandler(value, (data) => {
      if (data.length > 2048) {
        return '长度不可超过2048位字符'
      }
      if (!data.startsWith('/') || data.includes('?')) {
        return '路径配置必须以/开头，不支持携带参数'
      }
    }),
  )
}

// 验证URL查询参数
// export const validateUrlQueryString: FormValidator = (
//   value: number | string | string[] | number[],
//   callback: (error?: string) => void,
// ) => {
//   const reg = /^(([a-z_]\w*)+=\S*)+$/i
//   callback(
//     validateHandler(value, (data) => {
//       if (data.length > 2048) {
//         return '长度不可超过2048位字符'
//       }
//       return regExpValidateHandler(data, reg, 'URL查询字符串格式错误')
//     }),
//   )
// }

// 验证标题
export const validateTitle: FormValidator = (
  value: number | string | string[] | number[],
  callback: (error?: string) => void,
) => {
  const reg = /^[a-z0-9\u4E00-\u9FA5]{1,30}$/i
  callback(
    validateHandler(value, (data) => {
      if (data.length > 30) {
        return '标题长度为30位以内的字母，数字和汉字'
      }
      return regExpValidateHandler(
        data,
        reg,
        '标题为长度30位以内的汉字，字母和数字',
      )
    }),
  )
}

// 验证cname
// export const validateCName: FormValidator = (
//   value: number | string | string[] | number[],
//   callback: (error?: string) => void,
// ) => {
//   callback(
//     validateHandler(value, data =>
//       regExpValidateHandler(
//         data,
//         regexpMap.cname,
//         '请输入6 ~ 20 位字母和数字或-',
//       )),
//   )
// }

export async function validateRuleID(value: string) {
  const reg = /\D/g
  if (reg.test(value)) {
    return Promise.resolve(false)
  }
  return Promise.resolve(true)
}
